/**
  gui_server.java is part of Marioneta.

  Marioneta is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License.

  Marioneta is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
  
  @author martin
   Martin Edmundo Barriga Orozco, 2008
   martin.barriga@gulmore.org
 
  gui_server: Esta clase abre un Frame con dos objetivos en mente, primeramente
  se encarga de recibir los eventos del mouse (clic y movimiento) y keyboard 
  para enviarlos atravez de un socket.
  Tambien tiene la funcion de mostrar las imagenes del Escritorio remoto
 */

package escritorioremoto;

import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Frame;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

import java.net.Socket;
import java.io.IOException;


public class gui_server extends Frame {
    private Socket sock;
    ioServer objServLocal;
    
    private Image imgBackgroud;
    private int tam_x, tam_y;
    private boolean original_size;
    private imgServer serverX;
    doImgServer multi_imagenes;
   
    int contScr;
    
    /*
     * Esta variable contrla la disponibilidad de los listener, solo uno de ellos
     * podra ser usado, siempre y cuando este libre el mutex
     */
    private boolean mutex;
    
    /**
     * Cadena que contiene la descripcion de la pantalla, se recibe en el sig. formato
     * "~xxx,yyy"
     * donde:
     *      xxx resolucion en X
     *      yyy resolucion en Y
     */
    String scr_size_id="";
    
    public gui_server(){
        inicia_server_eventos();
        inicia_widgets();
    }
    
    /**
     * Constructor
     * @param s - socket
     */
    public gui_server( Socket s, doImgServer mi ){
        sock = s;
        objServLocal = new ioServer( sock );
        inicia_server_eventos();

        inicia_widgets();
        contScr=0;
        multi_imagenes = mi;
    }
    
    public gui_server( Socket s ){
        sock = s;
        objServLocal = new ioServer( sock );
        inicia_server_eventos();

        inicia_widgets();
        contScr=0;
    }
    
    
    //Este metodo podria ser sobre sobrecargado para que cada quien implemente
    //si propio protocolo de negociacion inicial.
    private void inicia_server_eventos(){
        objServLocal.initProc();
        try{
            //Se consigue el tamaño de la ventana remota
            scr_size_id = objServLocal.recibeStr();
            
            //Se crea el servidor que atiende a las imagenes
            //serverX = new imgServer( 5001 );
            serverX = new imgServer( 5001 );
            Thread obj = new Thread( serverX );
            obj.start();
            
            //Avisamos que se recibio resolucion y que la conexion esta LISTEN
            objServLocal.sendStr("OK");
            
        }
        catch( IOException e ){
            System.out.println("inicia_server_eventos: "+ e.getMessage() );
        }
    }
    
    @Override
    public void paint( Graphics g ) {
        if( imgBackgroud != null ) {
            g.drawImage( imgBackgroud, this.getInsets().left, this.getInsets().top, this );
            System.out.println("Se mando pintar la imagem en el form: Paint");
        }
    }
    
    @Override
    public void update( Graphics g ) {
        
        if( imgBackgroud != null ) {
            g.drawImage( imgBackgroud, this.getInsets().left, this.getInsets().top, this );
            System.out.println("Se mando pintar la imagen en el form: update");
        }
    }

    
    private void inicia_widgets(){
        //Se habilita el uso del recurso compartido
        mutex = true;
        
        this.addMouseListener( new MouseAdapter() {
            @Override public void mouseClicked(MouseEvent evt) {
                onClick_mouse(evt);
                
            }
        });
        this.addMouseMotionListener( new MouseMotionAdapter(){
            @Override public void mouseMoved(MouseEvent evt){
                onMove_mouse(evt);
            }
        });
        this.addKeyListener( new KeyAdapter(){
            @Override public void keyPressed(KeyEvent e){
                onKey_press( e );
            }
        });
        
        //f1 = new BorderLayout(2,2); //Verticales
        //f2 = new FlowLayout();      //Horizontales
        //f3 = new GridBagLayout();   //Revisar
        
        this.setTitle("Ventana del Servidor");
        
        this.calcular_scr();
        this.setSize(tam_x, tam_y);
        
        this.setVisible(true);
    }
    
    private void  onMove_mouse(MouseEvent evt){
        this.setTitle( evt.getX()+ "x"+evt.getY() ); 
        
        HiloMonitor ob = new HiloMonitor(this, evt);
        ob.start();
    }
    
    private void onClick_mouse( MouseEvent evt ){
        if (mutex){
            mutex = false;
            int x,y;
            if( original_size ){
                x = evt.getX()-this.getInsets().left;
                y = evt.getY()-this.getInsets().top;
            }
            else{
                x = (evt.getX()-this.getInsets().left)*2;
                y = (evt.getY()-this.getInsets().top)*2;
            }
            try{
                objServLocal.sendStr("*"+  x + ","+ y );
                imgBackgroud = serverX.getting_img();
                contScr+=1;
                this.setTitle("Ventana del Servidor: " +contScr);
                this.repaint();
                System.out.println("rePaint "+ contScr  +", invocado... [ OK ] ");
            }
            catch(IOException e  ){
                System.out.println("Error");
            }
            mutex = true;
        }
    }
    
    private void onKey_press( KeyEvent evt ){
        if(mutex){
            mutex = false;
            try{
                objServLocal.sendStr("@"+  evt.getKeyCode() + ",0" );
                imgBackgroud = serverX.getting_img();
                contScr+=1;
                this.setTitle("Ventana del Servidor: " +contScr);
                this.repaint();
                System.out.println("rePaint "+ contScr  +", invocado... [ OK ] ");
            }
            catch(IOException e  ){
                System.out.println("Error");
            }
            mutex = true;
        }
    }
    
    
    /*
     * Este metodo hace los calculos necesarios para hacer una aproximacion del 
     * tamaño del Frame que debemos crear, debera ser un tamaño en escala o 
     * incluso 1:1
     */
    private void calcular_scr(){
        int rX, rY, localX, localY;
        
        System.out.print("Calculando pantalla: "+ scr_size_id);
        //Sacamos los valores que sen han recojido
        rX = Integer.parseInt( scr_size_id.substring(1, scr_size_id.indexOf(".") ) );
        rY = Integer.parseInt( scr_size_id.substring( scr_size_id.indexOf(",") + 1 , scr_size_id.lastIndexOf(".") ) );
        
        //Obtenemos los valores de nuestra resolucion
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        
        //Ritual del desmembramiento de cadenas
        String strX = ""+ screenSize.getWidth();
        String strY = ""+ screenSize.getHeight();
        strX = strX.substring(0, strX.indexOf(".") );
        strY = strY.substring(0, strY.indexOf(".") );
        
        //Aplicamos el parser, y la comida esta casi lista!!
        localX = Integer.parseInt( strX );
        localY = Integer.parseInt( strY );
        
        if( rX >= localX || rY >= localY ){
            tam_x = rX/2+12;
            tam_y = rY/2+30;
            original_size = false;
        }
        else{
            tam_x = rX+12;
            tam_y = rY+30;
            original_size = true;
        }
        tam_x = rX+ this.getInsets().left + this.getInsets().right;
        tam_y = rY+ this.getInsets().top + this.getInsets().bottom;
        original_size = true;
    }
    
    /*
     * Metodos necesarios para el hilo monitor
     */
    
    public void setMutex(boolean m){
        this.mutex = m;
    }
    
    public boolean getMutex(){
        return this.mutex;
    }
    
    public boolean getOriginalSize(){
        return this.original_size;
    }
    
    public ioServer getIoServer(){
        return this.objServLocal;
    }
    
    public imgServer getImgServer(){
        return this.serverX;
    }
    
    public void setImgBackground(Image im){
        this.imgBackgroud = im;
        this.repaint();
    }
    
    //public void mousePressed(MouseEvent ev) {}
    //public void mouseExited(MouseEvent event) {}
    //public void mouseReleased(MouseEvent event) {}
    //public void mouseClicked(MouseEvent event) {}
    //public void mouseEntered(MouseEvent event) {}

}
